﻿using System;
using System.Linq;
using KuiHuaBaoDian.Services.Guide;
using UnityEditor;
using UnityEngine.UIElements;

namespace KuiHuaBaoDian.GuideGraph.Editor {

    [CustomElement(typeof(GuideAnchor))]
    public class GuideProperty_Anchor : IGuideProperty {

        public VisualElement GetField(string label, SerializedProperty sp) {
            var anchorXProperty = sp.FindPropertyRelative(nameof(GuideAnchor.X));
            var anchorYProperty = sp.FindPropertyRelative(nameof(GuideAnchor.Y));
            var field = new AnchorField {
                label = label,
                value = new GuideAnchor { X = anchorXProperty.floatValue, Y = anchorYProperty.floatValue },
            };
            field.RegisterCallback<ChangeEvent<GuideAnchor>>(evt => {
                anchorXProperty.floatValue = evt.newValue.X;
                anchorYProperty.floatValue = evt.newValue.Y;
                sp.serializedObject.ApplyModifiedPropertiesWithoutUndo();
            });
            return field;
        }
    }

    public class AnchorField : VisualElement, INotifyValueChanged<GuideAnchor> {

        private Label m_LabelField;
        private GuideAnchor m_Value;

        private Action<float, float> m_SetValueAction;

        public AnchorField() : base() {
            var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(assembly => assembly.GetName().Name == "UnityEditor.UIBuilderModule");
            var fieldType = assembly.GetType("Unity.UI.Builder.TransformOriginStyleField");
            var field = (VisualElement)Activator.CreateInstance(fieldType);
            var selector = field.Q("selector");
            selector.style.marginLeft = 0;
            selector.style.marginRight = 0;
            selector.style.paddingLeft = 6;
            selector.style.paddingRight = 6;
            selector.style.paddingTop = 6;
            selector.style.paddingBottom = 6;
            selector.style.flexDirection = FlexDirection.Row;
            var selectorType = selector.GetType();
            var selectedField = selectorType.GetField("pointSelected");
            var action = m_SetValueAction = (Action<float, float>)selectedField.GetValue(selector);
            action += ValueChanged;
            selectedField.SetValue(selector, action);
            var row = field.Q("unity-visual-input");
            m_LabelField = new Label() {
                name = "title-label"
            };
            m_LabelField.AddToClassList("title-label-last");
            row.Insert(0, m_LabelField);
            row.style.flexDirection = FlexDirection.Row;
            var focus = selector.Q("focus-rect");
            focus.style.display = DisplayStyle.None;
            var valueContent = field.Q("value-content");
            valueContent.parent.Remove(valueContent);
            Add(field);
        }

        private void ValueChanged(float x, float y) {
            var previousValue = m_Value;
            var newValue = new GuideAnchor { X = x, Y = 1 - y };
            SetValueWithoutNotify(newValue);
            var evt = ChangeEvent<GuideAnchor>.GetPooled(previousValue, newValue);
            evt.target = this;
            SendEvent(evt);
            var evt2 = EventBase<IGuideProperty.PropertyChangedEvent>.GetPooled();
            evt2.target = this;
            SendEvent(evt2);
        }

        public string label { get => m_LabelField.text; set => m_LabelField.text = value; }

        public GuideAnchor value {
            get => m_Value;
            set {
                if (panel != null) {
                    ValueChanged(value.X, value.Y);
                } else {
                    SetValueWithoutNotify(value);
                }
            }
        }

        public void SetValueWithoutNotify(GuideAnchor newValue) {
            m_SetValueAction.Invoke(newValue.X, 1 - newValue.Y);
            m_Value = newValue;
        }
    }
}
